﻿using Interface.DAO;
using JMI_Nucleo.Classe;
using JMI_Nucleo.Enumerador;
using JMI_Nucleo.JMIProvider;
using OR;
using OR.Enumerador;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Drawing;

namespace Dao
{
    public class EmpresaDao : IEmpresaDao<mEmpresa>
    {
        private mEmpresa infoEmpresa;
        private IEnderecoDao<mEndereco> daoEndereco;
        private IPessoaDao<mPessoa> daoPessoa;
        private IContatoDao<mContato> daoContato;
        private ITabelaImagemDao<mTabelaImagem> daoImagem;

        public EmpresaDao()
        {
            daoEndereco = DaoFactory<EnderecoDao>.Create();
            daoPessoa = DaoFactory<PessoaDao>.Create();
            daoContato = DaoFactory<ContatoDao>.Create();
            daoImagem = DaoFactory<TabelaImagemDao>.Create();
        }
        #region comando SQL
        const string cmdInsertSQL = @"INSERT INTO cadastro.empresa(codigo, datacadastro, inscmunicipal, 
                                      codibge, regimesituacaotributaria, pessoa, contato, endresidencial,
                                      endcorrespondencia,endcomercial,endcobranca)
                                      VALUES (@codigo, @datacadastro, @inscmunicipal, @codibge, 
                                      @regimesituacaotributaria, @pessoa, @contato, @endresidencial,
                                      @endcorrespondencia, @endcomercial, @endcobranca)";

        const string cmdUpdateSQL = @"UPDATE cadastro.empresa SET datacadastro=@datacadastro,
                                      inscmunicipal=@inscmunicipal, codibge=@codibge, 
                                      regimesituacaotributaria=@regimesituacaotributaria
                                      WHERE codigo =@PAR_COD_EMPRESA";

        const string cmdDeleteSQL = @"DELETE FROM cadastro.empresa WHERE codigo =@PAR_COD_EMPRESA";

        const string cmdSelectSQL = @"SELECT * FROM cadastro.empresa ";

        const string cmdConEmpresaPorFiltro = @"SELECT A.codigo, A.datacadastro, P.nome, P.apelido, P.CNPJ,
                                     C.telefone1, C.telefone2, C.telefone3, C.celular, C.fax, C.email, C.email1,
                                     C.site, C.fonecomercial FROM cadastro.empresa A
                                     INNER JOIN cadastro.pessoa P ON (A.pessoa = P.indice AND A.codigo = P.empresa)
                                     INNER JOIN cadastro.contato C ON (A.contato = C.indice AND A.codigo = C.empresa) ";

        const string cmdConEmpresaPorCNPJ = @"SELECT E.* FROM cadastro.empresa E, cadastro.pessoa P
                                     WHERE (E.pessoa = P.indice AND E.codigo = P.empresa)
                                     AND P.cnpj =@PAR_CNPJ";

        const string cmdRetornaCodigo = @"SELECT E.codigo FROM cadastro.empresa E, cadastro.pessoa P
                                     WHERE (E.pessoa = P.indice AND E.codigo = P.empresa)
                                     AND P.apelido =@PAR_APELIDO";

        const string cmdRetornaApelido = @"SELECT P.apelido FROM cadastro.empresa E, cadastro.pessoa P
                                     WHERE (E.pessoa = P.indice AND E.codigo = P.empresa)
                                     AND E.codigo =@PAR_CODIGO";
        #endregion
    
        #region Metodos publicos
        bool IEmpresaDao<mEmpresa>.Inserir(mEmpresa infoEmpresa)
        {
            bool sucesso = false;
            int idEndereco = 0;
            mEndereco _endereco;

            try
            {
                infoEmpresa.Pessoa.Indice = UtilBD.GetID(EngineBD.GetConexao, "cadastro.pessoa", "indice", infoEmpresa.Codigo);
                infoEmpresa.Pessoa.Empresa = infoEmpresa.Codigo;
                sucesso = daoPessoa.Inserir(infoEmpresa.Pessoa);

                if (sucesso)
                {
                    infoEmpresa.Contato.Indice = UtilBD.GetID(EngineBD.GetConexao, "cadastro.contato", "indice", infoEmpresa.Codigo);
                    infoEmpresa.Contato.Empresa = infoEmpresa.Codigo;
                    sucesso = daoContato.Inserir(infoEmpresa.Contato);
                }
                if (sucesso)
                {
                    idEndereco = UtilBD.GetID(EngineBD.GetConexao, "cadastro.endereco", "indice", infoEmpresa.Codigo);
                    for (int j = 0; j < infoEmpresa.ListaEndereco.Count; j++)
                    {
                        _endereco = infoEmpresa.ListaEndereco[j];
                        _endereco.Empresa = infoEmpresa.Codigo;
                        _endereco.Indice = idEndereco;
                        sucesso = daoEndereco.Inserir(_endereco);
                        if (sucesso)
                        {
                            switch (_endereco.Tipo)
                            {
                                case eTipoEndereco.Residencial: infoEmpresa.EnderecoResidencial = idEndereco; break;
                                case eTipoEndereco.Correspondencia: infoEmpresa.EnderecoCorrespondencia = idEndereco; break;
                                case eTipoEndereco.Comercial: infoEmpresa.EnderecoComercial = idEndereco; break;
                                case eTipoEndereco.Cobranca: infoEmpresa.EnderecoCobranca = idEndereco; break;
                            }
                        }
                        idEndereco++;
                        if (sucesso == false)
                            break;
                    }
                }
                if (sucesso)
                {
                    DbCommand _cmd = EngineBD.GetConexao.CreateCommand();
                    _cmd.CommandType = CommandType.Text;
                    _cmd.CommandText = cmdInsertSQL;
                    GeraParametro(ref _cmd, infoEmpresa, 1);
                    _cmd.Prepare();
                    sucesso = EngineBD.ExecuteNonQuery(_cmd);
                }           
                // Grava Imagem
                if (sucesso && infoEmpresa.Figura.ImgByte.Length > 0)
                {
                    infoEmpresa.Figura.Codigo = UtilBD.GetID(EngineBD.GetConexao, "cadastro.imggeral", "codigo", infoEmpresa.Codigo);
                    infoEmpresa.Figura.Chave = infoEmpresa.Codigo;
                    infoEmpresa.Figura.Empresa = infoEmpresa.Codigo;
                    infoEmpresa.Figura.TabelaVinculada = "empresa";
                    sucesso = daoImagem.Inserir(infoEmpresa.Figura);
                }
            }
            catch (Exception ex)
            {
                #region Grava log local
                mLog _info = new mLog();
                _info._TipoErro = TipoErro.Erro;
                _info.Mensagem = "Erro ao executar comando. " + ex.Message;
                _info.Metodo = "bool IEmpresaDao<mEmpresa>.Inserir(mEmpresa infoEmpresa)";
                _info.StackTrace = ex.StackTrace;
                _info.Tabela = String.Empty;
                LogLocal.Info = _info;
                LogLocal.Gravar();
                #endregion
            }
            return sucesso;
        }
        bool IEmpresaDao<mEmpresa>.Alterar(mEmpresa infoEmpresa)
        {
            bool sucesso = false;
            DbParameter p = null;

            try
            {
                sucesso = daoPessoa.Alterar(infoEmpresa.Pessoa, infoEmpresa.Pessoa.Indice, infoEmpresa.Pessoa.Empresa);
                if (sucesso)
                    sucesso = daoContato.Alterar(infoEmpresa.Contato, infoEmpresa.Contato.Indice, infoEmpresa.Contato.Empresa);
                if (sucesso)
                {
                    for (int j = 0; j < infoEmpresa.ListaEndereco.Count; j++)
                    {
                        sucesso = daoEndereco.Alterar(infoEmpresa.ListaEndereco[j], infoEmpresa.ListaEndereco[j].Indice, infoEmpresa.Codigo);
                        if (sucesso == false)
                            break;
                    }
                }
                if (sucesso)
                {
                    DbCommand _cmd = EngineBD.GetConexao.CreateCommand();
                    _cmd.CommandType = CommandType.Text;
                    _cmd.CommandText = cmdUpdateSQL;
                    GeraParametro(ref _cmd, infoEmpresa, 2);
                    p = _cmd.CreateParameter();
                    p.ParameterName = "@PAR_COD_EMPRESA";
                    p.Value = infoEmpresa.Codigo;
                    _cmd.Parameters.Add(p);
                    _cmd.Prepare();
                    sucesso = EngineBD.ExecuteNonQuery(_cmd);
                }
                // Grava Imagem
                if (sucesso && infoEmpresa.Figura.ImgByte.Length > 0)
                {
                    infoEmpresa.Figura.Chave = infoEmpresa.Codigo;
                    infoEmpresa.Figura.Empresa = infoEmpresa.Codigo;
                    infoEmpresa.Figura.TabelaVinculada = "empresa";
                    sucesso = daoImagem.Alterar(infoEmpresa.Figura);
                }
            }
            catch (Exception ex)
            {
                #region Grava log local
                mLog _info = new mLog();
                _info._TipoErro = TipoErro.Erro;
                _info.Mensagem = "Erro ao executar comando. " + ex.Message;
                _info.Metodo = "bool IEmpresaDao<mEmpresa>.Alterar(mEmpresa infoEmpresa)";
                _info.StackTrace = ex.StackTrace;
                _info.Tabela = String.Empty;
                LogLocal.Info = _info;
                LogLocal.Gravar();
                #endregion
            }
            return sucesso;
        }
        bool IEmpresaDao<mEmpresa>.Excluir(mEmpresa infoEmpresa)
        {
            bool sucesso = false;
            DbParameter p = null;

            try
            {
                // Excluir pessoa
                sucesso = daoPessoa.Excluir(infoEmpresa.Pessoa.Indice, infoEmpresa.Codigo);
                // Excluir contato
                sucesso = daoContato.Excluir(infoEmpresa.Contato.Indice, infoEmpresa.Codigo);
                // Excluir os possiveis endereços cadastrados
                daoEndereco.Excluir(infoEmpresa.EnderecoResidencial, infoEmpresa.Codigo);
                daoEndereco.Excluir(infoEmpresa.EnderecoCorrespondencia, infoEmpresa.Codigo);
                daoEndereco.Excluir(infoEmpresa.EnderecoComercial, infoEmpresa.Codigo);
                daoEndereco.Excluir(infoEmpresa.EnderecoCobranca, infoEmpresa.Codigo);
                DbCommand _cmd = EngineBD.GetConexao.CreateCommand();

                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdDeleteSQL;

                p = _cmd.CreateParameter();
                p.ParameterName = "@PAR_COD_EMPRESA";
                p.Value = infoEmpresa.Codigo;
                _cmd.Parameters.Add(p);

                _cmd.Prepare();

                sucesso = EngineBD.ExecuteNonQuery(_cmd);       
            }
            catch (Exception ex)
            {
                #region Grava log local
                mLog _info = new mLog();
                _info._TipoErro = TipoErro.Erro;
                _info.Mensagem = "Erro ao executar comando. " + ex.Message;
                _info.Metodo = "bool IEmpresaDao<mEmpresa>.Excluir(int Codigo)";
                _info.StackTrace = ex.StackTrace;
                _info.Tabela = String.Empty;
                LogLocal.Info = _info;
                LogLocal.Gravar();
                #endregion
            }
            return sucesso;
        }
        bool IEmpresaDao<mEmpresa>.ExisteCadastro()
        {
            bool retorno = false;

            DbDataReader rd = null;
            DbCommand _cmd = null;

            try
            {

                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdSelectSQL;

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    retorno = true;
            }
            finally
            {
                rd.Close();
            }
            return retorno;
        }

        short IEmpresaDao<mEmpresa>.GetCodigo(string Apelido)
        {
            short retorno = 0;

            DbDataReader rd = null;
            DbCommand _cmd = null;

            try
            {
                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdRetornaCodigo;

                p.ParameterName = "@PAR_APELIDO";
                p.Value = Apelido;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    retorno = Convert.ToInt16(rd["codigo"]);
            }
            finally
            {
                rd.Close();
            }
            return retorno;
        }

        string IEmpresaDao<mEmpresa>.GetApelido(int Codigo)
        {
            string retorno = String.Empty;

            DbDataReader rd = null;
            DbCommand _cmd = null;

            try
            {
                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdRetornaCodigo;

                p.ParameterName = "@PAR_CODIGO";
                p.Value = Codigo;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    retorno = rd["apelido"].ToString();
            }
            finally
            {
                rd.Close();
            }
            return retorno;
        }
                
        mEmpresa IEmpresaDao<mEmpresa>.GetEmpresaPorCNPJ(string CNPJ)
        {
            infoEmpresa = new mEmpresa();

            DbDataReader rd = null;
            DbCommand _cmd = null;
            JMIUtil objUtil = new JMIUtil();

            try
            {
                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdConEmpresaPorCNPJ;

                p.ParameterName = "@PAR_CNPJ";
                p.Value = objUtil.RemoveMascara(CNPJ);
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);

                if (rd.Read())
                    infoEmpresa = GetRdEmpresa(rd);
            }
            finally
            {
                rd.Close();
            }
            return infoEmpresa;
        }

        mEmpresa IEmpresaDao<mEmpresa>.GetEmpresa(int Codigo)
        {
            infoEmpresa = new mEmpresa();
             
            DbDataReader rd = null;
            DbCommand _cmd = null;
            string cmdSQL = String.Empty;

            try
            {
                cmdSQL = cmdSelectSQL;
                cmdSQL += "WHERE codigo =@PAR_COD_EMPRESA";

                _cmd = EngineBD.GetConexao.CreateCommand();

                DbParameter p = _cmd.CreateParameter();
                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdSQL;

                p.ParameterName = "@PAR_COD_EMPRESA";
                p.Value = Codigo;
                _cmd.Parameters.Add(p);

                rd = EngineBD.ExecuteDataReader(_cmd);
                                
                if (rd.Read())
                    infoEmpresa = GetRdEmpresa(rd);
            }
            finally
            {
                rd.Close();
            }
            return infoEmpresa;
        }

        List<mEmpresa> IEmpresaDao<mEmpresa>.GetListEmpresa()
        {
            List<mEmpresa> lstEmpresa = new List<mEmpresa>();
            DbDataReader rd = null;
            DbCommand _cmd = null;
            string cmdSQL = String.Empty;

            try
            {
                cmdSQL = cmdSelectSQL;
                cmdSQL += " ORDER BY codigo";
                _cmd = EngineBD.GetConexao.CreateCommand();

                _cmd.CommandType = CommandType.Text;
                _cmd.CommandText = cmdSQL;
                      
                rd = EngineBD.ExecuteDataReader(_cmd);

                while (rd.Read())
                {
                    infoEmpresa = GetRdEmpresa(rd);
                    lstEmpresa.Add(infoEmpresa);
                }
            }
            finally
            {
                if (rd != null)
                    rd.Close();
            }
            return lstEmpresa;
        }

        List<mEmpresa> IEmpresaDao<mEmpresa>.GetListaPorFiltro(mEmpresa infoEmpresa)
        {
            List<mEmpresa> lstEmpresa = new List<mEmpresa>();
            DbDataReader rd = null;
            DbCommand _cmd = null;
            string cmdSQL = String.Empty;

            try
            {
                cmdSQL = cmdConEmpresaPorFiltro;
            
                _cmd = EngineBD.GetConexao.CreateCommand();

                _cmd.CommandType = CommandType.Text;
                _cmd.Parameters.Clear();

                if (!String.IsNullOrEmpty(infoEmpresa.Pessoa.Apelido))
                {
                   cmdSQL += "WHERE P.apelido = @PAR_APELIDO ";
                   UtilBD.AdicionaParametro(ref _cmd, "@PAR_APELIDO", infoEmpresa.Pessoa.Apelido);
                }
                else if (!String.IsNullOrEmpty(infoEmpresa.Pessoa.Nome))
                {
                   cmdSQL += "WHERE P.nome = @PAR_NOME ";
                   UtilBD.AdicionaParametro(ref _cmd, "@PAR_NOME", infoEmpresa.Pessoa.Nome);
                }
                else if (!String.IsNullOrEmpty(infoEmpresa.Pessoa.CNPJ))
                {
                    cmdSQL += "WHERE P.cnpj = @PAR_CNPJ ";
                    UtilBD.AdicionaParametro(ref _cmd, "@PAR_CNPJ", infoEmpresa.Pessoa.CNPJ);
                }
                cmdSQL += "ORDER BY A.codigo";
                _cmd.CommandText = cmdSQL;
                rd = EngineBD.ExecuteDataReader(_cmd);

                while (rd.Read())
                {
                    infoEmpresa.Codigo = Convert.ToInt16(rd["codigo"]);
                    infoEmpresa.DataCadastro = Convert.ToDateTime(rd["datacadastro"]);
                    infoEmpresa.Pessoa.Nome = rd["nome"].ToString();
                    infoEmpresa.Pessoa.CNPJ = rd["CNPJ"].ToString();
                    infoEmpresa.Pessoa.Apelido = rd["apelido"].ToString();
                    infoEmpresa.Contato.Telefone1 = rd["telefone1"].ToString();
                    infoEmpresa.Contato.Telefone2 = rd["telefone2"].ToString();
                    infoEmpresa.Contato.Telefone3 = rd["telefone3"].ToString();
                    infoEmpresa.Contato.Celular = rd["celular"].ToString();
                    infoEmpresa.Contato.Fax = rd["fax"].ToString();
                    infoEmpresa.Contato.Email1 = rd["email"].ToString();
                    infoEmpresa.Contato.Email2 = rd["email1"].ToString();
                    infoEmpresa.Contato.Site = rd["site"].ToString();
                    infoEmpresa.Contato.FoneComercial = rd["fonecomercial"].ToString();
                    lstEmpresa.Add(infoEmpresa);
                    infoEmpresa = new mEmpresa();
                }
            }
            finally
            {
                if (rd != null)
                    rd.Close();
            }
            return lstEmpresa;
        }
        #endregion

        #region Metodos privados
        private void IncEndereco(int IndiceEndereco, short CodigoEmpresa)
        {
            List<mEndereco> lstTemp;

            lstTemp = daoEndereco.GetListEndereco(IndiceEndereco, CodigoEmpresa);

            if (lstTemp != null && lstTemp.Count > 0)
            {
                foreach (var item in lstTemp)
                {
                    item.Empresa = infoEmpresa.Codigo;
                    infoEmpresa.ListaEndereco.AdicionaItem(item);
                }
            }
        }
        private mEmpresa GetRdEmpresa(DbDataReader rd)
        {
            infoEmpresa = new mEmpresa();

            infoEmpresa.Codigo = Convert.ToInt16(rd["codigo"]);
            infoEmpresa.DataCadastro = Convert.ToDateTime(rd["datacadastro"]);
            infoEmpresa.InscMunicipal = rd["inscmunicipal"].ToString();
            infoEmpresa.IBGE = rd["codibge"].ToString();
            infoEmpresa.RegimeSituacaoTributaria = Convert.ToInt16(rd["regimesituacaotributaria"]);
            infoEmpresa.Pessoa = daoPessoa.GetPessoa(Convert.ToInt32(rd["pessoa"]), infoEmpresa.Codigo);
            infoEmpresa.Contato = daoContato.GetContato(Convert.ToInt32(rd["contato"]), infoEmpresa.Codigo);

            // Verifica se existe endereço residencial cadastrado
            IncEndereco(Convert.ToInt32(rd["endresidencial"]), infoEmpresa.Codigo);
            // Verifica se existe endereço de correspondência cadastrado
            IncEndereco(Convert.ToInt32(rd["endcorrespondencia"]), infoEmpresa.Codigo);
            // Verifica se existe endereço comercial cadastrado
            IncEndereco(Convert.ToInt32(rd["endcomercial"]), infoEmpresa.Codigo);
            // Verifica se existe endereço de cobrança cadastrado
            IncEndereco(Convert.ToInt32(rd["endcobranca"]), infoEmpresa.Codigo);
     
            infoEmpresa.Figura = daoImagem.GetImagem("empresa", infoEmpresa.Codigo);
            return infoEmpresa;
        }
        
        private void GeraParametro(ref DbCommand _cmd, mEmpresa obj, byte Acao)
        {
            _cmd.Parameters.Clear();

            if (Acao == 1) // Parametros para inclusão de dados
            {
                UtilBD.AdicionaParametro(ref _cmd, "@codigo", obj.Codigo);
                UtilBD.AdicionaParametro(ref _cmd, "@pessoa", obj.Pessoa.Indice);
                UtilBD.AdicionaParametro(ref _cmd, "@endresidencial", obj.EnderecoResidencial);
                UtilBD.AdicionaParametro(ref _cmd, "@endcorrespondencia", obj.EnderecoCorrespondencia);
                UtilBD.AdicionaParametro(ref _cmd, "@endcomercial", obj.EnderecoComercial);
                UtilBD.AdicionaParametro(ref _cmd, "@endcobranca", obj.EnderecoCobranca);
                UtilBD.AdicionaParametro(ref _cmd, "@contato", obj.Contato.Indice);
                UtilBD.AdicionaParametro(ref _cmd, "@datacadastro", obj.DataCadastro);
                UtilBD.AdicionaParametro(ref _cmd, "@inscmunicipal", obj.InscMunicipal);
                UtilBD.AdicionaParametro(ref _cmd, "@codibge", obj.IBGE == String.Empty ? 0 : Convert.ToInt32(obj.IBGE));
                UtilBD.AdicionaParametro(ref _cmd, "@regimesituacaotributaria", obj.RegimeSituacaoTributaria);
            }
            else if (Acao == 2) // Parametros para alteração de dados
            {
                UtilBD.AdicionaParametro(ref _cmd, "@datacadastro", obj.DataCadastro);
                UtilBD.AdicionaParametro(ref _cmd, "@inscmunicipal", obj.InscMunicipal);
                UtilBD.AdicionaParametro(ref _cmd, "@codibge", obj.IBGE == String.Empty ? 0 : Convert.ToInt32(obj.IBGE));
                UtilBD.AdicionaParametro(ref _cmd, "@regimesituacaotributaria", obj.RegimeSituacaoTributaria);
            }
        }
        #endregion
    }
}
